﻿using Azure;
using DeHeng_Mes.Model;
using Microsoft.VisualBasic.Logging;
using S7.Net;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using zjxj_repair.Bean;
using zjxj_repair.Bean.Model;
using zjxj_repair.Service;
using zjxj_repair.Table;
using zjxj_repair.Utils;
using zjxj_repair.WindowsForm;

namespace zjxj_repair.Tasks
{
    public class RepairTask
    {
        #region 成员实例
        EnableServices enableServices = new EnableServices();
        #endregion

        /// <summary>
        /// 按钮颜色跳动
        /// </summary>
        /// <returns></returns>
        public async Task ButtonColoer(Button lm, Button cxlm, Button mt1, Button lm2, Button cxlm2, Button mt2, Button resetButton)
        {
            Tools.DeviceLogText($"[初始化操作]-心跳警示线程启动！");

            while (true)
            {
                List<ConfigModelBean> readList = ConfigModelInit.ReadList;

                try
                {
                    foreach (var item in readList)
                    {
                        if (item.IsCollected)
                        {
                            switch (item.ToolName)
                            {
                                case "LM1":
                                    Coloer(lm, item.HartBeat);
                                    break;
                                case "CXLM1":
                                    Coloer(cxlm, item.HartBeat);
                                    break;
                                case "LM2":
                                    Coloer(lm2, item.HartBeat);
                                    break;
                                case "CXLM2":
                                    Coloer(cxlm2, item.HartBeat);
                                    break;
                                case "MT1":
                                    Coloer(mt1, item.HartBeat);
                                    break;
                                case "MT2":
                                    Coloer(mt2, item.HartBeat);
                                    break;
                            }
                        }
                    }
                }
                catch(Exception e)
                {
                    Tools.DeviceLogText($"[初始化操作]-心跳警示线程启动失败，原因是[{e.Message}]");
                }

                // 工具状态设置
                if (!string.IsNullOrEmpty(StaticBean.ToolName) && !StaticBean.ToolName.Equals("空"))
                {
                    // 当前工具状态
                    bool isEnable = enableServices.IsEnable(StaticBean.ToolName);

                    resetButton.Invoke(new Action(() => resetButton.Text = isEnable ? "使用中" : "未使用"));
                }

                await Task.Delay(100);
            }
        }

        /// <summary>
        /// Ip设置线程
        /// </summary>
        /// <param name="mainForm"></param>
        /// <returns></returns>
        public async Task IpSet(MainForm mainForm, Button repairData)
        {
            await Task.Delay(1000);
            while (true)
            {
                try
                {
                    Dictionary<string, string> dictionary = StaticBean.ConfigList
                    .ToDictionary(x => x.ToolName, x => $"{x.ToolIp.Split('.')[2]}.{x.ToolIp.Split('.')[3]}:{x.ToolPort}");

                    // 使用递归方式遍历所有子控件
                    TraverseControls(mainForm, dictionary);

                    repairData.Invoke(new Action(() => repairData.Text = StaticBean.RepairData.Count.ToString()));

                    await Task.Delay(1000);
                }
                catch (Exception e)
                {
                    Console.Write(e.Message);
                }
            }
        }

        /// <summary>
        /// 铆接设备连接线程
        /// </summary>
        /// <returns></returns>
        public async Task LMHart()
        {
            while (true)
            {
                if (ConfigModelInit.ReadList.Count > 0)
                    break;

                await Task.Delay(100);
            }

            Tools.DeviceLogText("[初始化操作]-拉铆枪连接线程启动！");

            CancellationTokenSource _cts = new CancellationTokenSource();

            var token = _cts.Token;

            List<ConfigModelBean> configList = ConfigModelInit.ReadList;

            foreach (var item in configList)
            {
                try
                {
                    if (item.ToolName.Contains("MT"))
                        continue;

                    _ = Task.Run(async () =>
                    {
                        Plc plc = new Plc(CpuType.S7200Smart, item.ToolIp, 0, 1);

                        await plc.OpenAsync(token);

                        item.IsCollected = plc.IsConnected;

                        item.ToolBean = plc;

                        //启动心跳监测线程
                        await Task.Run(() => sendHeartBeat(item, token));
                    });
                }
                catch(Exception e)
                {
                    Tools.DeviceLogText($"[初始化操作]-拉铆枪连接线程启动失败，原因是{e.Message}");

                    //启动重连线程
                    //ReconnectToPlc(item, token);
                }

                await Task.Delay(100);
            }
        }

        /// <summary>
        /// Socket信息消费线程
        /// </summary>
        /// <returns></returns>
        public async Task ConsumptionResponse(Button enableButton)
        {
            while (true)
            {
                await Task.Delay(50);

                if (!(ConfigModelInit.ReadList.Count > 0) && !(SoketSendList.SendList.Count > 0))
                    continue;

                foreach (var item in ConfigModelInit.ReadList)
                {
                    try
                    {
                        if (item.ToolName.Contains("LM") || !item.IsCollected)
                            continue;

                        TcpClient toolBean = (TcpClient)item.ToolBean;

                        if (!toolBean.Connected)
                            continue;

                        NetworkStream networkStream = toolBean.GetStream();

                        byte[] buffer = new byte[1024];

                        int bytesRead = await networkStream.ReadAsync(buffer, 0, buffer.Length);

                        if (bytesRead > 0)
                        {
                            string response = Encoding.ASCII.GetString(buffer, 0, bytesRead);

                            await responseConsumption(response, item, enableButton);
                        }
                    }
                    catch (Exception e)
                    {
                        Tools.ProduceLogText($"[拧紧枪通讯操作]-[{item.ToolName}]接收指令失败，原因是[{e.Message}]");

                        // 恢复按钮颜色
                        enableButton.Invoke(new Action(() => enableButton.BackColor = Color.White));

                        // 锁定设备
                        await Tools.SendToServer(item, "00200042001         \0", item.ToolName);

                        enableServices.ToolEnable(item.ToolName, "0");
                    }
                }
            }
        }

        /// <summary>
        /// 消费响应
        /// </summary>
        /// <param name="response"></param>
        /// <param name="item"></param>
        private async Task responseConsumption(string response, ConfigModelBean item, Button enableButton)
        {
            try
            {
                // 提取MID
                string mid = response.Substring(4, 4);

                Tools.ProduceLogText($"[拧紧枪通讯操作]-[{item.ToolName}]接收[{mid}]指令[{response}]");

                switch (mid)
                {
                    case "0002": // 连接确认
                                 // 清除发送
                        SoketSendList.RemoveData(item.ToolName + "_" + "00200001            \0");
                        break;

                    case "0005":
                        // 使能命令响应
                        (bool, string) value1 = SoketSendList.IsContains("00200043");

                        // 锁定命令响应
                        (bool, string) value2 = SoketSendList.IsContains("00200042");

                        // 订阅响应
                        (bool, string) value3 = SoketSendList.IsContains("0060");

                        // 程序号命令响应
                        (bool, string) value4 = SoketSendList.IsContains("0018");

                        if (value1.Item1)
                        {
                            // 使能响应处理
                            SoketSendList.RemoveData(value1.Item2);

                            // 使能标记
                            item.IsEnable = true;
                        }
                        else if (value2.Item1)
                        {
                            // 使能响应处理
                            SoketSendList.RemoveData(value2.Item2);
                        }
                        else if (value3.Item1)
                        {
                            // 清除发送
                            SoketSendList.RemoveData(value3.Item2);
                        }
                        else if(value4.Item1)
                        {
                            // 程序号响应处理
                            SoketSendList.RemoveData(value4.Item2);

                            // 发送使能
                            await Tools.SendToServer(item, "00200043001         \0", item.ToolName);
                        }
                        break;

                    case "0061": // 拧紧结果
                                 // 响应结果确认
                        await Tools.SendToServer(item, "00200062001         \0", item.ToolName);

                        // 解析结果
                        TighteningResult tighteningResult = ParseTighteningResult(response);

                        if (tighteningResult != null && tighteningResult.IsValid)
                        {
                            // 存储数据
                            enableServices.SaveTightenData(tighteningResult, StaticBean.PointName, StaticBean.VinCode, StaticBean.ToolName, StaticBean.ToolModel);

                            if (tighteningResult.IsOK && !StaticBean.Model.Contains("离线模式"))
                            {
                                // 恢复按钮颜色
                                enableButton.Invoke(new Action(() => enableButton.BackColor = Color.White));

                                // 锁定设备
                                await Tools.SendToServer(item, "00200042001         \0", item.ToolName);

                                enableServices.ToolEnable(item.ToolName, "0");
                            }
                        }
                        break;

                    case "9999": // 心跳响应
                        await Task.Delay(1000);

                        item.HartBeat = false;
                        // 清除发送
                        SoketSendList.RemoveData(item.ToolName + "_" + "00209999            \0");
                        break;

                    case "0004":
                        // 程序号命令响应
                        (bool, string) value = SoketSendList.IsContains("00230018");

                        if (value.Item1)
                        {
                            // 程序号响应处理
                            SoketSendList.RemoveData(value.Item2);

                            // 发送使能
                            await Tools.SendToServer(item, "00200043001         \0", item.ToolName);
                        }
                        break;

                    default:
                        // 处理其他响应
                        break;
                }
            }
            catch (Exception e)
            {
                Tools.ProduceLogText($"[拧紧枪通讯操作]-[{item.ToolName}]接收指令失败，原因是[{e.Message}][{response}]");

                // 恢复按钮颜色
                enableButton.Invoke(new Action(() => enableButton.BackColor = Color.White));

                // 锁定设备
                await Tools.SendToServer(item, "00200042001         \0", item.ToolName);

                enableServices.ToolEnable(item.ToolName, "0");
            }
        }

        /// <summary>
        /// 马头枪拧紧设备连接线程
        /// </summary>
        /// <returns></returns>
        public async Task DesoutterControllerHart()
        {
            while (true)
            {
                if (ConfigModelInit.ReadList.Count > 0)
                    break;

                await Task.Delay(100);
            }

            List<ConfigModelBean> configModelBeans = ConfigModelInit.ReadList.Where(x => x.ToolName.Contains("MT")).ToList();

            foreach (var item in configModelBeans)
            {
                _ = Task.Run(async() =>
                {
                    try
                    {
                        Tools.DeviceLogText($"[初始化操作]-[{item.ToolName}]拧紧枪连接线程启动！");

                        TcpClient client = new TcpClient();

                        IPAddress ip = IPAddress.Parse(item.ToolIp);

                        await client.ConnectAsync(ip, int.Parse(item.ToolPort));

                        NetworkStream stream = client.GetStream();

                        if (client.Connected)
                        {
                            item.ToolBean = client;

                            item.IsCollected = true;

                            // 发送连接指令
                            bool isSend = await Tools.SendToServer(item, "00200001            \0", item.ToolName);

                            while (true)
                            {
                                List<string> sendList = SoketSendList.SendList;

                                if (isSend && !sendList.Contains(item.ToolName + "_" + "00200001            \0"))
                                {
                                    // 发送订阅指令
                                    bool isSend1 = await Tools.SendToServer(item, "00200060            \0", item.ToolName);

                                    while (true)
                                    {
                                        if (isSend1 && !sendList.Contains(item.ToolName + "_" + "00200060            \0"))
                                        {
                                            //启动心跳线程
                                            await Task.Run(() => sendHeartBeat(item));

                                            break;
                                        }

                                        await Task.Delay(100);

                                    }

                                    break;
                                }
                                await Task.Delay(100);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Tools.DeviceLogText($"[初始化操作]-[{item.ToolName}]拧紧枪连接线程启动失败，原因是[{e.Message}]");

                        //启动重连线程
                        //ReconnectToPlc(item);
                    }
                });
            }
        }

        /// <summary>
        /// 拧紧程序重连线程
        /// </summary>
        /// <param name="item"></param>
        private async void ReconnectToPlc(ConfigModelBean item)
        {
            Tools.DeviceLogText($"[初始化操作]-[{item.ToolName}]拧紧枪重连线程启动！");

            while (!item.IsCollected)
            {
                try
                {
                    (string ToolIp, string ToolPort) value = ConfigModelInit.ReadList.Where(x => x.ToolName.Equals(item.ToolName)).Select(x => (x.ToolIp, x.ToolPort)).FirstOrDefault();

                    IPAddress ip = IPAddress.Parse(value.ToolIp);

                    TcpClient client = new TcpClient();

                    await client.ConnectAsync(ip, int.Parse(item.ToolPort));

                    NetworkStream stream = client.GetStream();

                    if (client.Connected)
                    {
                        // 发送连接指令
                        bool isSend = await Tools.SendToServer(item, "00200001            \0", item.ToolName);

                        item.ToolBean = client;

                        while (true)
                        {
                            List<string> sendList = SoketSendList.SendList;

                            if (isSend && !sendList.Contains(item.ToolName + "_" + "00200001            \0"))
                            {
                                item.IsCollected = true;

                                //启动心跳线程
                                await Task.Run(() => sendHeartBeat(item));

                                break;
                            }
                            await Task.Delay(100);
                        }
                    }
                }
                catch (Exception e) 
                {
                    item.IsCollected = false;

                    Tools.DeviceLogText($"[初始化操作]-[{item.ToolName}]拧紧枪重连线程启动失败[是[{e.Message}]");
                }
                await Task.Delay(3000);
            }
        }

        /// <summary>
        /// 拧紧程序心跳线程
        /// </summary>
        /// <param name="item"></param>
        private async void sendHeartBeat(ConfigModelBean item)
        {
            Tools.DeviceLogText($"[初始化操作]-[{item.ToolName}]拧紧枪心跳线程启动！");

            while (item.IsCollected)
            {
                try
                {
                    if (item.HartBeat)
                        return;

                    string hartStr = "00209999            \0";

                    bool isSend = await Tools.SendToServer(item, hartStr, item.ToolName);

                    if (!isSend)
                    {
                        item.IsCollected = false;

                        //启动重连线程
                        //ReconnectToPlc(item);

                        return;
                    }
                    else
                    {
                        item.HartBeat = true;
                    }
                }
                catch(Exception e)
                {
                    Tools.DeviceLogText($"[初始化操作]-[{item.ToolName}]拧紧枪心跳线程启动失败[{e.Message}]");

                    item.IsCollected = false;

                    //启动重连线程
                    //ReconnectToPlc(item);

                    return;
                }

                await Task.Delay(4500);
            }
        }

        #region 私有方法
        /// <summary>
        /// 解析马头反馈数据
        /// </summary>
        /// <param name="rawData"></param>
        /// <returns></returns>
        public TighteningResult ParseTighteningResult(string rawData)
        {
            var result = new TighteningResult();

            try
            {
                // 验证基本长度（至少包含关键字段位置）
                if (rawData.Length < 100)
                {
                    result.IsValid = false;
                    return result;
                }

                // 1. 查找关键字段位置
                int statusIndex = FindFieldIndex(rawData, "09");
                int torqueIndex = FindFieldIndex(rawData, "15");
                int angleIndex = FindFieldIndex(rawData, "19");

                // 2. 解析拧紧状态 (09)
                if (statusIndex != -1 && rawData.Length > statusIndex + 2)
                {
                    // 状态位在字段ID后的第1位
                    char statusChar = rawData[statusIndex + 2];
                    result.IsOK = statusChar == '1';
                }

                // 3. 解析扭矩值 (15)
                if (torqueIndex != -1 && rawData.Length >= torqueIndex + 8)
                {
                    // 扭矩值在字段ID后的6位数字
                    string torqueStr = rawData.Substring(torqueIndex + 2, 6);
                    if (int.TryParse(torqueStr, out int torqueInt))
                    {
                        result.Torque = torqueInt / 100.0; // 除以100得到实际扭矩值
                    }
                }

                // 4. 解析角度值 (19)
                if (angleIndex != -1 && rawData.Length >= angleIndex + 7)
                {
                    // 角度值在字段ID后的5位数字
                    string angleStr = rawData.Substring(angleIndex + 2, 5);
                    if (int.TryParse(angleStr, out int angleInt))
                    {
                        result.Angle = angleInt;
                    }
                }

                // 标记为有效解析
                result.IsValid = true;
            }
            catch
            {
                result.IsValid = false;
            }

            return result;
        }

        /// <summary>
        /// 查找字段位置
        /// </summary>
        /// <param name="data"></param>
        /// <param name="fieldId"></param>
        /// <returns></returns>
        private int FindFieldIndex(string data, string fieldId)
        {
            int index = data.IndexOf(fieldId);

            if (index != -1)
            {
                if (index > 0 && char.IsDigit(data[index - 1]))
                {
                    return -1;
                }

                if (index + fieldId.Length + 1 >= data.Length)
                {
                    return -1;
                }
            }

            return index;
        }

        /// <summary>
        /// 心跳监测线程
        /// </summary>
        /// <param name="plcConfig"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        private async Task sendHeartBeat(ConfigModelBean plcConfig, CancellationToken token)
        {
            Tools.DeviceLogText($"[初始化操作]-[{plcConfig.ToolName}]铆枪心跳线程启动！");

            while (plcConfig.IsCollected && !token.IsCancellationRequested)
            {
                try
                {
                    while (true)
                    {
                        Plc toolBean = (Plc)plcConfig.ToolBean;

                        bool heart = (bool)toolBean.Read("Q1152.0");

                        if (heart == plcConfig.HartBeat)
                        {
                            plcConfig.HartBeatCount++;

                            if(plcConfig.HartBeatCount == 10)
                            {
                                //启动重连线程
                                //ReconnectToPlc(plcConfig, token);
                            }
                        }
                        else
                        {
                            plcConfig.HartBeat = heart;

                            plcConfig.HartBeatCount = 0;
                        }

                        await Task.Delay(1000);
                    }
                }
                catch (Exception e)
                {
                    plcConfig.IsCollected = false;

                    Tools.DeviceLogText($"[初始化操作]-[{plcConfig.ToolName}]铆枪心跳线程启动失败，原因是[{e.Message}]");

                    await Task.Delay(1000);

                    //启动重连线程
                    //ReconnectToPlc(plcConfig, token);
                    return;
                }
            }
        }

        /// <summary>
        /// 重连线程
        /// </summary>
        /// <param name="plcConfig"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        private async void ReconnectToPlc(ConfigModelBean plcConfig, CancellationToken token)
        {
            Tools.DeviceLogText($"[初始化操作]-[{plcConfig.ToolName}]铆枪重连线程启动！");

            while (!plcConfig.IsCollected && !token.IsCancellationRequested)
            {
                try
                {
                    (string ToolIp, string ToolPort) value = ConfigModelInit.ReadList.Where(x => x.ToolName.Equals(plcConfig.ToolName)).Select(x => (x.ToolIp, x.ToolPort)).FirstOrDefault();

                    Plc plc = new Plc(CpuType.S7200Smart, value.ToolIp, 0, 1);

                    await plc.OpenAsync(token);

                    plcConfig.IsCollected = true;

                    plcConfig.ToolBean = plc;

                    //启动心跳线程
                    await Task.Run(() => sendHeartBeat(plcConfig, token));

                    break;
                }
                catch (Exception ex)
                {
                    Tools.DeviceLogText($"[初始化操作]-[{plcConfig.ToolName}]铆枪重连线程启动失败，原因是[{ex.Message}]");

                    plcConfig.IsCollected = false;
                }
                await Task.Delay(3000);
            }
        }

        /// <summary>
        /// 递归查找控件
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="dictionary"></param>
        private void TraverseControls(Control parent, Dictionary<string, string> dictionary)
        {
            foreach (Control child in parent.Controls)
            {
                // 处理当前控件
                if (child is TextBox textBox)
                {
                    string baseName = child.Name.Split('_').FirstOrDefault();

                    if (!string.IsNullOrEmpty(baseName) &&
                        dictionary.TryGetValue(baseName, out string ip))
                    {
                        // 安全跨线程更新UI
                        if (textBox.InvokeRequired)
                        {
                            textBox.Invoke(new Action(() => textBox.Text = ip));
                        }
                        else
                        {
                            textBox.Text = ip;
                        }
                    }
                }

                // 递归遍历子控件
                if (child.HasChildren)
                {
                    TraverseControls(child, dictionary);
                }
            }
        }

        /// <summary>
        /// 根据心跳控制颜色跳动
        /// </summary>
        /// <param name="button"></param>
        /// <param name="hartBeat"></param>
        private void Coloer(Button button, bool hartBeat)
        {
            Color color = hartBeat ? Color.Green : Color.White;

            button.Invoke(new Action(() =>
            {
                button.BackColor = color;
            }));
        }
        #endregion
    }
}
